package log

import (
	"fmt"
	"log"
	"os"
	"runtime"
	"runtime/debug"
	"time"
)

const (
	NoLv = iota
	TRACE
	DEBUG
	INFO
	WARN
	ERROR
	FATAL
)

var (
	logStr     = []string{"", "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"}
	logLevel   = DEBUG
	logger     LogInf
	withCaller = false
)

func init() {
	logger = log.New(os.Stdout, "", 0)
}

func SetLogLevel(level int) {
	if level < 1 {
		level = TRACE
	} else if level > FATAL {
		level = FATAL
	}
	logLevel = level
}

func SetOutput(l LogInf) {
	logger = l
}

// 打开文件名和行号的打印
func WithCallerPrint() {
	withCaller = true
}

func output(level int, format string, a ...any) {
	v, t, c := "", time.Now().Format("2006-01-02 15:04:05.000"), getCallerInfo()
	if level >= logLevel {
		v = fmt.Sprintf(format, a...)
		logger.Println(t + "|" + logStr[level] + "|" + c + v)
	} else if level == NoLv {
		if format == "" {
			v = fmt.Sprint(a...)
		} else {
			v = fmt.Sprintf(format, a...)
		}
		logger.Println(t + "|" + c + v)
	}
}

func Trace(info string, args ...any) {
	output(TRACE, info, args...)
}

func Debug(info string, args ...any) {
	output(DEBUG, info, args...)
}

func Info(info string, args ...any) {
	output(INFO, info, args...)
}

func Warn(info string, args ...any) {
	output(WARN, info, args...)
}

func Error(info string, args ...any) {
	output(ERROR, info, args...)
}

func Fatal(info string, args ...any) {
	output(FATAL, info, args...)
	debug.PrintStack()
	os.Exit(0)
}

func Print(args ...any) {
	output(NoLv, "", args...)
}

func Printf(info string, args ...any) {
	output(NoLv, info, args...)
}

func Println(args ...any) {
	output(NoLv, "", args...)
}

func getCallerInfo() string {
	callerInfo := ""
	if withCaller {
		_, file, line, _ := runtime.Caller(3)
		callerInfo = fmt.Sprintf(" %s:%d", file, line) + "|"
	}
	return callerInfo
}
